#include <reg52.h>
#include <intrins.h>

// 定义LCD1602相关引脚
sbit RS = P2^0;   // RS引脚
sbit RW = P2^1;   // RW引脚
sbit E = P2^2;    // E引脚
sbit DATA = P0;   // 数据线引脚

// 定义HX711相关引脚
sbit PD_SCK = P1^5;   // 时钟引脚
sbit DOUT = P1^6;     // 数据引脚

// 定义独立按键引脚
sbit KEY = P3^2;

// 定义全局变量
bit tareFlag = 0;     // 去皮操作标志位
long tareValue = 0;   // 去皮值

// LCD1602写命令
void LcdWriteCmd(unsigned char cmd) {
    RS = 0;
    RW = 0;
    DATA = cmd;
    _nop_();
    E = 1;
    _nop_();
    E = 0;
    _nop_();
}

// LCD1602写数据
void LcdWriteData(unsigned char dat) {
    RS = 1;
    RW = 0;
    DATA = dat;
    _nop_();
    E = 1;
    _nop_();
    E = 0;
    _nop_();
}

// LCD1602初始化
void LcdInit() {
    LcdWriteCmd(0x38);   // 设置16x2显示模式
    LcdWriteCmd(0x0c);   // 开启光标并关闭闪烁
    LcdWriteCmd(0x06);   // 光标右移
    LcdWriteCmd(0x01);   // 清除显示
    LcdWriteCmd(0x80);   // 设置显示位置为第一行第一个字符
}

// HX711读取数据
long Hx711Read() {
    unsigned char i;
    long value = 0;
    
    while(DOUT);
    
    for (i = 0; i < 24; i++) {
        PD_SCK = 1;
        value = value << 1;
        _nop_();
        if (DOUT) {
            value++;
        }
        PD_SCK = 0;
        _nop_();
    }
    
    for (i = 0; i < 1; i++) {
        PD_SCK = 1;
        _nop_();
        PD_SCK = 0;
        _nop_();
    }
    
    return value;
}

// 延时函数
void Delay(unsigned int n) {
    unsigned int i, j;
    
    for (i = n; i > 0; i--) {
        for (j = 110; j > 0; j--);
    }
}

// 显示重量和去皮值
void DisplayWeight(long weight) {
    unsigned char i;
    unsigned long temp;
    unsigned char str[] = "Weight:";
    
    temp = weight;
    
    for (i = 7; i >= 0; i--) {
        str[7 - i + 7] = temp % 10 + '0';
        temp /= 10;
    }
    
    for (i = 0; i < 8; i++) {
        LcdWriteData(str[i]);
    }
    
    if (tareFlag) {
        unsigned char strTare[] = " Tare:";
        temp = tareValue;
        
        for (i = 7; i >= 0; i--) {
            strTare[7 - i + 6] = temp % 10 + '0';
            temp /= 10;
        }
        
        for (i = 0; i < 7; i++) {
            LcdWriteData(strTare[i]);
        }
    }
}

// 去皮操作
void Tare() {
    tareFlag = 1;
    tareValue = Hx711Read();
}

// 主函数
void main() {
    long weight;
    
    LcdInit();   // 初始化LCD1602
    Delay(5);
    
    while (1) {
        weight = Hx711Read();   // 读取重量
        
        if (tareFlag) {
            weight -= tareValue;   // 计算净重
        }
        
        DisplayWeight(weight);   // 显示重量
        
        if (KEY == 0) {
            Delay(50);
            if (KEY == 0) {
                Tare();   // 执行去皮操作
                while (!KEY);
                Delay(10);
            }
        }
    }
}
